<?php
namespace Kuoqi\Model;
use Kuoqi\Error;
use Kuoqi\Format;
use Kuoqi\Config;

/**
 * Class Model
 * @package Kuoqi\Model
 * User kuoqi
 * Datetime 2022/3/1 11:07
 * Remark 数据库模型调用完整版
 */
class Model extends \Kuoqi\Model{
    static protected $client;
    protected $is_valied = false;//是否为有效的表单,如果有数据则为true,没数据则外false
    protected $_primary_key = 0;//唯一标识
    protected $_primary_name = '';//唯一标识的键名

    /*---------被使用的属性列表---------*/
    protected $isCreate = true;//是否为新创建的对象，默认是
    //当前对象属性对象列表
    protected $attrlist = array();
    //所有的属性信息
    //这里是基础的属性列表，键值为列表的基础属性
    //version:1.00.00
    /**
     * @var array 属性信息列表，当前数据表的属性信息
     * User kuoqi
     * Datetime 2022/3/4 10:40
     * Remark
     */
    protected $attributes = array(
        'id',
        'create_time',
        'update_time',
        'status',
        'remark'
    );

    /**
     * @var string 模型对应数据表名称
     * User kuoqi
     * Datetime 2022/3/4 10:35
     * Remark 如果不设置默认使用当前模型的模型名称作为当前模型使用的数据表名
     */
    protected $table_name = '';

    /**
     * @var string
     * User kuoqi
     * Datetime 2022/3/9 11:28
     * Remark 当前命名空间
     */
    protected $namespace = '';

    /**
     * @var string
     * User kuoqi
     * Datetime 2022/3/9 12:23
     * Remark 当前对象名
     */
    protected $classname = '';

    /**
     * @var string
     * User kuoqi
     * Datetime 2022/3/10 9:39
     * Remark 当前路由信息
     */
    protected $route = '';

    /**
     * @var null
     * User kuoqi
     * Datetime 2022/3/9 11:28
     * Remark 包含query
     */
    public $query = null;


    /**
     * @var array
     * User kuoqi
     * Datetime 2022/3/4 17:14
     * Remark 场景信息
     */
    protected $scale = array(
        'add'=>'',//填写基础字段信息，比如id.
        'save'=>'',
        'del'=>'',
    );

    /**
     * @var array
     * User kuoqi
     * Datetime 2022/3/4 17:14
     * Remark 字段信息设计
     */
    protected $fields = array(
        'id'=>'索引为必填',
        'sort'=>'排序为必填',
        'status'=>'状态信息为必填',
        'create_time'=>'创建时间为必填',
        'update_time'=>'更新时间为必填',
        'remark'=>'备注信息为必填',
    );

    /**
     * @var array
     * User kuoqi
     * Datetime 2022/3/4 17:14
     * Remark 条件信息设计
     */
    protected $condition = array(
        'id'=>'require',
        'sort'=>'intval',
        'status'=>'intval',
        'create_time'=>'intval',
        'update_time'=>'intval',
        'remark'=>'string',
    );

    //对象初始化
    //version:1.00.00
    public function __construct($attrs = array()){

        //将属性写入到属性数组信息中
        foreach($this->attributes as $it){
            //这里是属性额外属性写入
            $opts = array(
                'isChanged'=>isset($attrs[$it])?true:false,//判定这个值是否已经发生改变
            );
            $attr = new Model\AttrbutesModel($it,isset($attrs[$it])?$attrs[$it]:null,$opts);
            $this->attrlist[$it] = $attr;
        }

        //初始化基本的操作
        $this->__init();
        //初始化迷行字段验证
        $this->initColumns();
    }


    /**
     * 对象初始化的实际操作，在__construct之后执行本操作，初始化对象的相关信息
     * createby kuoqi at 2022/8/16 23:06
     * @throws Error
     */
    public function __init(){
        $this->route = get_class($this);
        $this->classname = Format::getClassname($this);
        $this->namespace = Format::getClassns($this);
        //获取本模型名称
        if(!$this->table_name){
            $tablename = Format::getClassname($this);
            $modelname = Format::getModelName($tablename,'Model');
            $this->table_name = \Kuoqi\Route::hump2code($modelname);
        }
        $this->query = new \Kuoqi\DbDriver\PdoDriver;
        //配置数据库类型
        $this->query->target(Config::get('DB_TARGET'));
        $this->query->connect();
        $this->query->returnData = false;
        $this->query->table($this->table_name);
    }

    //获取字段的数据
    private function getColumns(){
        //判定缓存是否存在
        if((!Config::get('DEBUG'))&&Config::get('DBMODEL_CACHETIME')&&($colums = Cache($this->table_name,'','','/module_table'))){

        }else{
            $colums = $this->query->getColumns();//获取所有数据表的字段信息进行规范
            Cache($this->table_name,$colums,86400,'/module_table');
        }
        return $colums;
    }

    public function __destory(){
        Error::process("模型销毁[]成功");
    }

    public function beforeBehavior(){}

    /**
     * 获取唯一的键名ID
     * @return string
     */
    public function getPrimaryName(){
        return $this->_primary_name;
    }
    /**
     * 获取唯一的ID
     * vbase
     * @return int
     */
    public function getPrimaryKey(){
        if($this->_primary_key){

        }else{
            foreach ($this->attrlist as $item){
                if($item->isIncrement){
                    $this->_primary_key = $item->getValue();
                }
            }
        }
        return $this->_primary_key;
    }

    /**
     * @param string $scale
     * @return bool
     * User kuoqi
     * Datetime 2022/3/9 10:34
     * Remark 验证数据信息，验证场景信息
     */
    public function validata($scale = ''){
        $validata = new Validata();
        $validata
            ->bindScale($this->scale)//绑定场景列表信息
            ->setMessage($this->fields)//配置字段的文本信息,可配置为字段或者为数据信息
            ->setData($this->attrlist)//配置数据信息
            ->setCondition($this->condition)//配置条件信息
            ->setScale($scale)//配置场景值信息
            ->check();//进行验证数据信息
        if($validata->isValied()){
            $this->is_valied = true;
        }else{
            $this->setError($validata->getError());
            $this->is_valied = false;
        }
        return $validata->isValied();
    }

    /**
     * 列出单条子对象
     * @param $modelName
     * @param $modelRex
     * @return mixed
     */
    public function hasOne($modelName,$modelRex){
        $clsname = $this->namespace.''.$modelName.'Model';
        $cls = new $clsname();
        $obj = $cls->find();
        return $obj;
    }



    /**
     * @return array|mixed
     * User kuoqi
     * Datetime 2022/3/9 10:34
     * Remark 新增保存
     */
    protected function saveInsert(){
        //组装数据信息
        $data = array();
        foreach($this->attrlist as $item){
            if($item->isValied()){
                //是可以用于数据写入的字段
                $data[$item->getKey()] = $item->getValue();
            }
        }
        $this->query->data($data);
        $this->is_valied = true;
        $this->_primary_key = $this->query->insert();
        if($this->getPrimaryName()){
            $this->query->where(array($this->getPrimaryName()=>$this->getPrimaryKey()));
        }
        return $this->_primary_key;
    }

    /**
     * @return bool
     * User kuoqi
     * Datetime 2022/3/9 10:34
     * Remark 编辑保存
     */
    protected function saveUpdate(){
        //这个时候应该是有属性值的，所以，不需要字段重新认同
        $data = array();
        foreach($this->attrlist as $item){
            if($item->isValied()){
                //是可以用于数据写入的字段
                $data[$item->getKey()] = $item->getValue();
            }
        }
        if($this->getPrimaryName()){
            $this->query->where(array($this->getPrimaryName()=>$this->getPrimaryKey()));
        }
        $this->query->data($data);
        return ($this->query->save()===false)?false:true;
    }

    //初始化字段信息,拉取数据表信息进行配置
    public function initColumns(){
        $colums = $this->getColumns();
        if($colums){
            //然后根据已经有的属性列表进行数据相关的存储
            foreach ($colums as $v){
                if(isset($v['colname'])&&(isset($this->attrlist[$v['colname']]))){
                    $this->attrlist[$v['colname']]->setDatatype($v['data_type']);
                    $this->attrlist[$v['colname']]->setComment($v['column_comment']);
                    $this->attrlist[$v['colname']]->setExtra($v['extra']);
                    //判定是否为自动增加，如果是则直接进入到自动增加，也就是本文的唯一索引
                    if($this->attrlist[$v['colname']]->isIncrement){
                        $this->_primary_name = $this->attrlist[$v['colname']]->getKey();
                    }
                }
            }
        }else{
            throw new Error('模型'.$this->classname.'未绑定数据表',array(
                '请定义【$this->table_name】'
            ));
        }
    }

    //保存当前
    public function save(){
        $this->beforeBehavior();
        if($this->isCreate){
            return $this->saveInsert();
        }else{
            return $this->saveUpdate();
        }
    }

    /**
     * @return $this
     * User kuoqi
     * Datetime 2022/3/9 10:34
     * Remark 获取当前
     */
    public function find(){
        $info = $this->query->field($this->attributes)->find();
        if($info === false){
            $this->is_valied = false;
            return $this;
        }else{
            $this->is_valied = true;
        }
        $this->isCreate = false;//这个不是创建了
        //将属性写入到列表里面
        foreach($this->attrlist as $key=>$item){
            if(isset($info[$key])){
                //这个值存在，存在即合理
                //初始化这个值，意味着这个值没有被修改
                $this->attrlist[$key]->initValue($info[$key]);
            }
        }
        //返回当前对象本生
        return $this;
    }

    /**
     * @return array
     * User kuoqi
     * Datetime 2022/3/9 10:34
     * Remark 获取列表数据信息
     */
    public function all(){
        $list = $this->query->field($this->attributes)->select();
        $array = array();
        foreach($list as $k=>$v){
            $array[] = new $this->route($v);
        }
        return $array;
    }

    /**
     * 删除
     * @return bool
     */
    public function delete(){
        return ($this->query->delete()===false)?false:true;

    }

    /**
     * 设置一个单独的属性
     * @param $attrname
     * @param $attrval
     * @return null
     */
    public function setAttributes($attrname,$attrval){
        if($this->attrlist&&isset($this->attrlist[$attrname])){
            return $this->attrlist[$attrname]->setValue($attrval);
        }else{
            \Kuoqi\Error::warning(__METHOD__.'属性['.$attrname.']不存在,请检查',$this);
            return null;
        }
    }

    /**
     * 获取一个单独属性
     * @param $attrname
     * @return null
     */
    public function getAttributes($attrname){
        if($this->attrlist&&isset($this->attrlist[$attrname])){
            return $this->attrlist[$attrname]->getValue();
        }else{
            \Kuoqi\Error::warning(__METHOD__.'属性['.$attrname.']不存在,请检查',$this);
            return null;
        }
    }

    /**
     * 设置一个单独的属性
     * @param $attrname
     * @param $attrval
     * @return null
     */
    public function setAttr($attrname,$attrval){
        return $this->setAttributes($attrname,$attrval);
    }

    /**
     * 配置attrs
     * @param $attrs
     * @return bool
     */
    public function setAttrs($attrs){
        foreach($attrs as $k=>$v){
            $this->setAttributes($k,$v);
        }
        return true;
    }

    /**
     * 获取一个单独属性
     * @param $attrname
     * @return null
     */
    public function getAttr($attrname){
        return $this->getAttributes($attrname);
    }

    /**
     * 判断属性是否存在
     * @param $attrname
     * @return bool
     */
    public function hasAttr($attrname){
        if($this->attrlist&&isset($this->attrlist[$attrname])){
            return true;
        }else{
            return false;
        }
    }


    /**
     * get_called_class
     * @param $id
     * @return mixed
     */
    public static function findByid($id){
        $query = self::retClass(get_called_class());
        $query->query->where(array('id'=>$id));
        return $query->find();
    }

    /**
     * 回调方法，设置属性值信息
     * @param $propertyname
     * @param $propertyval
     * @return null|void
     */
    public function offsetSet($propertyname,$propertyval){
        return $this->setAttributes($propertyname,$propertyval);
    }

    /**
     * 调用方法，获取属性信息
     * @param $property
     * @return mixed|null|void
     */
    public function offsetGet($property){
        return $this->getAttributes($property);
    }

    /**
     * 判定是否有数据
     * @return bool
     */
    public function isValied(){
        return $this->is_valied;
    }

    /**
     * 将数据转换成基础的数组信息
     * @return array
     * User kuoqi
     * Datetime 2022/3/3 12:22
     * Remark
     */
    public function toArray(){
        $arr = array();
        foreach($this->attrlist as $k=>$v){
            $arr[$k] = $v->getValue();
        }
        return $arr;
    }

    /**
     * 获取属性
     * @param $attrname
     * @return null
     */
    public function __get($attrname){
        return $this->getAttributes($attrname);
    }

    /**
     * 设置一些常用的属性的方法，当然这个属性是不存在的那种
     * @param $attrname
     * @param $attrval
     * @return null
     */
    public function __set($attrname,$attrval){
        return $this->setAttributes($attrname,$attrval);//设置属性
    }

    /**
     * 调用方法
     * @param $func
     * @param $params
     * @return null
     * @throws \ReflectionException
     */
    public function __call($func,$params){
        try{
            $invoke = new \Kuoqi\Invoke($this->query);
            $method = $invoke->getMethod($func);
            //$data = $method->invokeArgs($this->query,$params);
            $method->invokeArgs($this->query,$params);
            $obj = $invoke->exportInstance();//导出操作对象信息
            return $obj;
        }catch(Error $err){
            $err->quit();
        }
    }

    /**
     * 获取表格名称
     * @return string
     */
    static public function getTablename(){
        $query = self::retClass(get_called_class());
        return $query->table_name;
    }

    /**
     * 快速创建db
     * createby kuoqi at 2022/8/17 10:09
     * @return mixed
     */
    static public function db(){
        $query = self::retClass(get_called_class());
        return $query->query;
    }

    /**
     * 获取一个对象
     * @param $clsname
     * @return mixed
     */
    static public function retClass($clsname){
        return new $clsname;
    }

}